
#import "ColorView.h"
#import <math.h>
#import <libc.h>
#import <dpsclient/wraps.h>
#import <appkit/color.h>
#import <appkit/Button.h>
#import <appkit/Application.h>
#import <appkit/NXColorWell.h>

@implementation ColorView

- initFrame:(NXRect *)frameRect
{
	[super initFrame:frameRect];
	srandom(getpid());
	count = 0;
	colChange = 1;
	flip = 0;
	speed = 68;
	granularity = 150;
	maxBright = 1.0;
	minBright = 0.0;
	[NXApp loadNibSection:"ColorPrefs.nib" owner:self];
	winNum=[[self window] windowNum];

	// initial color is a bright blue.
	staticColor = NXConvertRGBToColor(0.0, 0.0, 1.0);
	currentColor = NXConvertRGBToColor(0.0, 0.0, 1.0);
	nextColor = NXConvertRGBToColor(0.0, 0.0, 1.0);
	[colorWell setColor:staticColor];
	return self;
}

- sizeTo:(NXCoord)width :(NXCoord)height
{
	[super sizeTo:width :height];
	mywidth = width;
	myheight = height;
	return self;
}

NXColor fade(currentColor, nextColor, tick, granularity)
NXColor currentColor, nextColor;
int tick, granularity;
{
	float fadeVal = tick * 1.0 / granularity;
	float r, g, b;
	NXColor tempColor;
    
	float r1 = NXRedComponent(currentColor);
	float r2 = NXRedComponent(nextColor);
	float g1 = NXGreenComponent(currentColor);
	float g2 = NXGreenComponent(nextColor);
	float b1 = NXBlueComponent(currentColor);
	float b2 = NXBlueComponent(nextColor);

	r = r1 + fadeVal * (r2 - r1);
    	g = g1 + fadeVal * (g2 - g1);
	b = b1 + fadeVal * (b2 - b1);
	tempColor = NXConvertRGBToColor(r, g, b);
	//fprintf(stderr, "Colors: %f %f %f\n", r, g, b);
	return tempColor;
}

- oneStep
{
	float brMult = maxBright - minBright;
	if (brMult < 0.0) brMult = 0.0;
	brMult = brMult/MAXINTF;
	
	tick = ++tick % speed; // allows us to change fade speed
	if (!colChange) showColor = staticColor; // no fades
	else if (!tick) { // only fade colors when right tick
	if (colRandom) { // fade to new (random) color
		count = ++count % granularity;
		if (!count) {
			currentColor = nextColor;
			nextColor = NXConvertRGBToColor(random() * brMult +
			  minBright, random() * brMult + minBright, random()
			  * brMult + minBright);
		}
		showColor = fade(currentColor, nextColor, count, granularity);
	} else { // fade color in and out
		count = ++count % granularity;
		if (!count) { if (!flip) {
			currentColor =
			  NXChangeBrightnessComponent(staticColor, minBright);
			nextColor =
			  NXChangeBrightnessComponent(staticColor, maxBright);
			flip = 1;
		} else {
			nextColor =
			  NXChangeBrightnessComponent(staticColor, minBright);
			currentColor =
			  NXChangeBrightnessComponent(staticColor, maxBright);
			flip = 0;
		} }
		showColor = fade(currentColor, nextColor, count, granularity);
	} }
	if (!tick || !colChange) [self update]; // only update when needed
	//fprintf(stderr,"tick=%d, count=%d\n",tick,count);
	return self;
}

- drawSelf:(const NXRect *)rects :(int)rectCount
{
	if (!rects || !rectCount) return self;
	
	NXSetColor(showColor);
	NXRectFill(rects);
	
	PScurrentmouse(winNum, &curX, &curY);
	/* Test the cursor */
	if (mywidth - curX + myheight - curY <= 10.0)
		[self show]; // get Pref panel if in upper rt. corner


	return self;
}

- (BOOL)isBoringScreenSaver
{	// I hope I set this right...
	return NO;
}

- (BOOL) useBufferedWindow
{ // unbuffered, so a call to update will always call drawself
  // to fill the window with color...
	return NO;
}


- show
{
	[myPrefWindow orderFront:nil];
	return self;
}

- newColor:sender
{
    staticColor = [sender color];
    return self;
}

- newMaxBright:sender
{
	maxBright = [sender floatValue];
	if (minBright > maxBright) {
		minBright = maxBright;
		[minSlider setFloatValue:minBright];
	}
	return self;
}

- newMinBright:sender
{
	minBright = [sender floatValue];
	if (minBright > maxBright) {
		maxBright = minBright;
		[maxSlider setFloatValue:maxBright];
	}
	return self;
}

- newGranularity:sender
{
    granularity = [sender intValue];
    return self;
}

- newSpeed:sender
{
    speed = [sender intValue];
    return self;
}

- colorsChange:sender
{
    colChange = [sender state];
    flip = 0; count = 0; tick = 0;
    return self;
}

- colorsRandom:sender
{
    colRandom = [sender state];
    count = 0; tick = 0;
    return self;
}


@end
